﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TireSizesCalculator.Controller;
using TireSizesCalculator.Model;
using TireSizesCalculator.Properties;


namespace TireSizesCalculator.View
{
    public partial class TireSizeCalculator : UserControl
    {
        private TireSizeController _controller;
        private Timer _timer;
        private TireSize _tire;


        public TireSizeCalculator()
        {
            InitializeComponent();

            _timer = new Timer();
            _timer.Interval = 2000;
            _timer.Tick += new EventHandler(TimeElapsed);
            _controller = new TireSizeController();
            panGraphics.Controller = _controller;

            LoadComboboxesValues();
        }


        #region Interface
        
        /// <summary>
        /// Wyszukuje opony dopasowane do podanego rozmiaru
        /// </summary>
        /// <param name="width">Szerokość opony</param>
        /// <param name="profile">Profil opony</param>
        /// <param name="radius">Średnica opony</param>
        /// <param name="error">Maksymalna dopuszczalna wartość błędu wyrażona w procentach</param>
        /// <returns>Lista dopasowanych rozmiarów wraz z ich błędem</returns>
        public List<TireMatch> FindMatchingTires(int width, int profile, int radius, double error)
        {
            TireSize tire = new TireSize(width, profile, radius);
            return FindMatchingTires(tire, error);
        }

        public void ShowMatchingTires(int width, int profile, int radius, double error)
        {
            nudErrorPercentage.Value = (decimal)error;
            


        }

        /// <summary>
        /// Wyszukuje opony dopasowane do podanego rozmiaru
        /// </summary>
        /// <param name="tire">Rozmiar opony wejściowej</param>
        /// <param name="error">Maksymalna dopuszczalna wartość błędu wyrażona w procentach</param>
        /// <returns>Lista dopasowanych rozmiarów wraz z ich błędem</returns>
        public List<TireMatch> FindMatchingTires(TireSize tire, double error)
        {
            if (!_controller.CheckSize(tire))
            {
                return null;
            }

            return _controller.GetMatchingSizes(tire, error);
        }

        /// <summary>
        /// Sprawdza, czy podany rozmiar opony jest prawidłowy
        /// </summary>
        /// <param name="width">Szerokość opony</param>
        /// <param name="profile">Profil opony</param>
        /// <param name="radius">Średnica opony</param>
        /// <returns>Wartość określającą, czy podany rozmiar jest poprawny</returns>
        public bool CheckTireSize(int width, int profile, int radius)
        {
            TireSize tire = new TireSize(width, profile, radius);
            return CheckTireSize(tire);
        }

        /// <summary>
        /// Sprawdza, czy podany rozmiar opony jest prawidłowy
        /// </summary>
        /// <param name="tire">Razmiar opony do sprawdzenia</param>
        /// <returns>Wartość określającą, czy podany rozmiar jest poprawny</returns>
        public bool CheckTireSize(TireSize tire)
        {
            return _controller.CheckSize(tire);
        }

        /// <summary>
        /// Pobiera wszystkie dostępne rozmiary opon
        /// </summary>
        /// <returns>Lista dostępnych rozmiarów opon</returns>
        public List<TireSize> GetTireSizes()
        {
            return _controller.GetTireSizes();
        }

        #endregion

        #region Properties

        public Color TireFrontColor
        {
            get
            {
                return panGraphics.TireFrontColor;
            }
            set
            {
                panGraphics.TireFrontColor = value;
            }
        }

        public Color TireSideColor
        {
            get
            {
                return panGraphics.TireSideColor;
            }
            set
            {
                panGraphics.TireSideColor = value;
            }
        }

        public Color ArrowLineColor
        {
            get
            {
                return panGraphics.ArrowLineColor;
            }
            set
            {
                panGraphics.ArrowLineColor = value;
            }
        }

        public Color LineColor
        {
            get
            {
                return panGraphics.LineColor;
            }
            set
            {
                panGraphics.LineColor = value;
            }
        }

        public Color TextColor
        {
            get
            {
                return panGraphics.TextColor;
            }
            set
            {
                panGraphics.TextColor = value;
            }
        }

        public bool ShowGraphic
        {
            get
            {
                return panGraphics.Visible;
            }
            set
            {
                panGraphics.Visible = value;
            }
        }

        public bool ShowEditors
        {
            get
            {
                return panEditors.Visible;
            }
            set
            {
                panEditors.Visible = value;
            }
        }

        public string SizesFile
        {
            get
            {
                
                return _controller.SizesFile;
            }
            set
            {
                _controller.SizesFile = value;
                LoadComboboxesValues();
            }
        }

        #endregion


        private void LoadComboboxesValues()
        {
            cmbWidth.SelectedIndex = -1;
            cmbWidth.Items.Clear();
            foreach (int value in _controller.GetWidths())
            {
                cmbWidth.Items.Add(value);
            }
            if (cmbWidth.Items.Count > 0)
            {
                cmbWidth.SelectedIndex = 0;
            }

            cmbProfile.SelectedIndex = -1;
            cmbProfile.Items.Clear();
            foreach (int value in _controller.GetProfiles())
            {
                cmbProfile.Items.Add(value);
            }
            if (cmbProfile.Items.Count > 0)
            {
                cmbProfile.SelectedIndex = 0;
            }

            cmbRadius.SelectedIndex = -1;
            cmbRadius.Items.Clear();
            foreach (int value in _controller.GetRadiuses())
            {
                cmbRadius.Items.Add(value);
            }
            if (cmbRadius.Items.Count > 0)
            {
                cmbRadius.SelectedIndex = 0;
            }
        }



        private void btnCheck_Click(object sender, EventArgs e)
        {
            HideError();
            lstResults.Items.Clear();

            if (cmbWidth.SelectedIndex < 0 || cmbProfile.SelectedIndex < 0 || cmbRadius.SelectedIndex < 0)
            {
                ShowError(Resources.StrErrorMissingData);
                return;
            }

            bool correct = _controller.CheckSize(_tire);
            if (!correct)
            {
                ShowError(Resources.StrErrorWrongSize);
                return;
            }

            List<TireMatch> results = _controller.GetMatchingSizes(_tire, (double)nudErrorPercentage.Value);
            ShowResults(results);
        }

        private void ShowResults(List<TireMatch> results)
        {
            foreach (TireMatch element in results)
            {
                ListViewItem item = new ListViewItem(element.Tire.ToString());
                item.SubItems.Add(String.Format(Resources.StrDoubleFormat, element.Mismatch));
                item.SubItems.Add(element.Rim.MinRimSize);
                item.SubItems.Add(element.Rim.RimSize);
                item.SubItems.Add(element.Rim.RimSizeMax);
                lstResults.Items.Add(item);
            }
        }
        
        private void ShowError(String error)
        {
            lblError.Text = error;
            lblError.Visible = true;
            _timer.Start();
        }

        private void HideError()
        {
            _timer.Stop();
            lblError.Visible = false;
        }

        private void TimeElapsed(object sender, EventArgs e)
        {
            HideError();
        }

        private void TireSelected(object sender, EventArgs e)
        {
            if (cmbWidth.SelectedIndex > -1 &&
                cmbProfile.SelectedIndex > -1 &&
                cmbRadius.SelectedIndex > -1)
            {
                _tire = new TireSize((int)cmbWidth.SelectedItem, (int)cmbProfile.SelectedItem, (int)cmbRadius.SelectedItem);
                bool correct = _controller.CheckSize(_tire);
                if (!correct)
                {
                    ShowError(Resources.StrErrorWrongSize);
                    return;
                }

                panGraphics.TireMain = _tire;
            }
        }

        private void lstResults_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstResults.SelectedIndices.Count > 0)
            {
                var tire = new TireSize(lstResults.SelectedItems[0].SubItems[0].Text);
                panGraphics.TireRight = tire;
            }
            else
            {
                panGraphics.TireRight = null;
            }
        }

        private void panGraphics_SizeChanged(object sender, EventArgs e)
        {
            panGraphics.Refresh();
        }
    }
}
